/**
 * @copyright Copyright (c) 2025 
 * CSG Digital Grid Technology (Guangdong) Co., Ltd.
 * @author xxxcsg
 * @brief OpenHarmony 轻量系统采集服务（CollectorService）实现
 * @details 基于 OpenHarmony SAMGR 框架的系统服务，核心功能包括本地数据采集与 MQTT OTA 升级集成：
 *          1. 服务注册：通过 SYS_SERVICE_INIT 注册为系统服务，服务标识为 COLLECTOR_SVR
 *          2. 本地采集任务：初始化时创建独立采集线程（优先级2，栈大小1024），循环2次向 /userdata/collect/collector.txt 写入计数数据（间隔5秒）
 *          3. OTA 升级集成：本地采集任务完成后，调用 mqtt_ota_demo() 启动 MQTT 协议的 OTA 升级客户端
 *          4. 服务接口：实现 SAMGR 服务必需的 GetName/Initialize/MessageHandle/GetTaskConfig 接口，支持 LPC 通信调用
 *          5. 日志输出：通过 HILOG 打印服务启动、线程运行、文件操作等关键日志，便于问题排查
 * @note 1. 依赖 OpenHarmony 系统组件：samgr_lite、thread_adapter、hilog、iunknown 等
 *       2. 依赖外部模块：mqtt_ota.h（提供 mqtt_ota_demo() OTA 升级客户端接口）
 *       3. 采集文件路径固定为 /userdata/collect/collector.txt，需确保目录已存在且具备读写权限
 *       4. 采集任务默认仅执行2次（计数1-2），可通过修改循环条件（cnt < 2）调整采集次数
 * @attention 1. 服务标识 COLLECTOR_SVR 需在系统中唯一，避免与其他服务冲突
 *            2. 线程栈大小（1024）、优先级（2）等配置需根据系统资源情况调整，避免资源不足导致线程创建失败
 *            3. 调用 mqtt_ota_demo() 后，程序会进入 OTA 客户端的阻塞循环（保持连接），需确保 OTA 模块初始化正常
 *            4. 若 /userdata/collect 目录不存在，需提前创建，否则文件写入会失败（日志输出 open file fail）
 */
#include <stdio.h>
#include "ohos_types.h"
#include "ohos_init.h"
#include "hilog/log.h"
#include "thread_adapter.h"
#include "time_adapter.h"
#include "iunknown.h"
#include "service.h"
#include "samgr_lite.h"
#include "mqtt_ota.h"

typedef struct DefaultFeatureApi {
    INHERIT_IUNKNOWN;
    void (*Call)(IUnknown *iUnknown);
} DftFeatApi;

typedef struct CollectorService {
    INHERIT_SERVICE;
    INHERIT_IUNKNOWNENTRY(DftFeatApi);
    Identity identity;
} CollectorService;

#define COLLECTOR_SERVICE "COLLECTOR_SVR"

static const char *GetName(Service *service)
{
    (void)service;
    return COLLECTOR_SERVICE;
}

static void *TaskEntry(void *argv)
{
    HILOG_INFO(LOG_CORE, "TaskEntry Enter....[%d]", pthread_self());
    uint32 cnt = 0;
    do
    {
        cnt++;
        printf("hello collector! --  %d\n", cnt);
        FILE* fp = fopen("/userdata/collect/collector.txt", "a+");
        if(!fp) {
            HILOG_ERROR(LOG_CORE, "open file fail");
            continue;
        }

        fprintf(fp, "collector: %d\n", cnt);
        fflush(fp);
        fclose(fp);

        sleep(5);

    }while(cnt < 2);

    mqtt_ota_demo();
    printf("hello collector! --  end\n");

    return NULL;
}

static BOOL Initialize(Service *service, Identity identity)
{
    CollectorService *svr = (CollectorService *)service;
    svr->identity = identity;

    ThreadAttr attr = {"collector thread", 1024, 2, 0, 0};
    ThreadId threadId = (ThreadId)THREAD_Create(TaskEntry, NULL, &attr);

    HILOG_INFO(LOG_CORE, "collector service[%s], thread[%u] starting, Time: [%11u]"
            , service->GetName(service), threadId, SAMGR_GetProcessTime());
    return TRUE;
}

static BOOL MessageHandle(Service *service, Request *msg)
{
    HILOG_INFO(LOG_CORE, "[LPC MessageHandle][thread:%u] msgId<%d>: %s \n",
            pthread_self(), msg->msgId, (char *)msg->data);
    (void)service;
    return FALSE;
}

static TaskConfig GetTaskConfig(Service *service)
{
    HILOG_INFO(LOG_CORE, "[LPC GetTaskConfig][thread:%u]\n", pthread_self());
    (void)service;
    TaskConfig config = {LEVEL_HIGH, PRI_BELOW_NORMAL,
        0x800, 20, SHARED_TASK};
    return config;
}

static void Call(IUnknown *iUnknown)
{
    HILOG_INFO(LOG_CORE, "[LPC Call API][thread:%u]\n", pthread_self());
    (void)iUnknown;
}

static CollectorService g_collector = {
    .GetName = GetName,
    .Initialize = Initialize,
    .MessageHandle = MessageHandle,
    .GetTaskConfig = GetTaskConfig,
    DEFAULT_IUNKNOWN_ENTRY_BEGIN,
    .Call = Call,
    DEFAULT_IUNKNOWN_ENTRY_END,
};

static void Init(void)
{
    HILOG_INFO(LOG_CORE, "collector service Init, thread [%u]", pthread_self());
    SAMGR_GetInstance()->RegisterService((Service *)&g_collector);
    SAMGR_GetInstance()->RegisterDefaultFeatureApi(COLLECTOR_SERVICE, GET_IUNKNOWN(g_collector));
    HILOG_INFO(LOG_CORE, "[Register service:%s] Time: %llu", COLLECTOR_SERVICE, SAMGR_GetProcessTime());
}

SYS_SERVICE_INIT(Init);

